package com.base;

import lombok.extern.slf4j.Slf4j;
import org.mapstruct.ap.shaded.freemarker.template.utility.CollectionUtils;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.EvaluationException;
import org.springframework.expression.Expression;
import org.springframework.expression.ParseException;
import org.springframework.expression.common.TemplateParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;

import java.util.List;

/**
 * Spel
 *
 * @description:
 * @author: cyj
 * @date 2022 -09-15 11:55:34
 */
@Slf4j
public class Spel {

    /**
     * SPEL_EXPRESSION_PARSER
     */
    private static final SpelExpressionParser SPEL_EXPRESSION_PARSER = new SpelExpressionParser();

    /**
     * Gets value by expression 通用spel
     *
     * @param <T>     parameter
     * @param exp     exp
     * @param model   model
     * @param rsClass rs class
     * @return the value by expression
     */
    public static <T> T executeRule(String exp, Object model, Class<T> rsClass) {
        try {
            EvaluationContext evaluationContext = new StandardEvaluationContext();
            evaluationContext.setVariable("model", model);
            T value = SPEL_EXPRESSION_PARSER.parseExpression(exp).getValue(evaluationContext, rsClass);
            log.info("expression: {}, model: {}, result---> {}", exp, model, value);
            return value;
        } catch (EvaluationException | ParseException e) {
            log.warn("spel error: {}", e.getMessage());
            throw e;
        }
    }

    /**
     * Gets string by list exp 命中一个规则则返回
     * exps元素会spilt["->"], 第一段数据是一个返回boolean的spel表达式，第二段是执行返回值！
     *
     * @param exps  exps
     * @param model model
     * @return the string by list exp
     */
    public static String executeRules(List<String> exps, Object model) {
        if (null == exps) {
            return null;
        }
        for (String exp :
                exps) {
            String[] split = exp.split("->");
            if (split.length != 2) {
                throw new RuntimeException("不符合方法规范, 必须满足exp.split(\"->\") == 2, 第一段数据是一个返回boolean的spel表达式，第二段是执行返回值！");
            }
            if (executeRule(split[0], model, Boolean.class)) {
                log.info("命中规则：{}", split[0]);
                return split[1];
            }
        }
        throw new RuntimeException("无法命中规则！");
    }

}
